# -*- coding: utf-8 -*-

from django.template import Context, loader, RequestContext
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.core.context_processors import csrf
from content_adm.models import Student, Course, Mark, Competence, CompinCrs, MarkforComp, Profession, CompforProf, Coefficient, Update
import datetime
from django.db.models import Max
from django.db import connections



# функция обновления базы программы из данных базы LMS
def update_local_database():
	now = datetime.date.today()							# получаем текущую дату
	update_students(now)								# функция обновления таблицы студентов
	update_total_marks(now)								# функция обновления таблицы средних/итоговых оценок
	update_courses(now)									# функция обновления таблицы курсов
	update_competence_marks(now)						# функция обновления таблицы оценок по компетенциям


# функция обновления таблицы студентов
def update_students(now):
	time_interval = datetime.timedelta(0)
	ic = 0
	update_now = 0
	try:
		updates_stud = Update.objects.filter(upd_type__exact=0).aggregate(last=Max('upd_date'))
		last_stud_update = updates_stud.get('last') 									# получаем дату последнего апдейта студентов
		time_interval = now - last_stud_update											# считаем разницу относительно текущей даты
		ic = int(Coefficient.objects.get(coef_name="upd_int_stud").coef_value)			# получаем интервал обновлений
		coef = Coefficient.objects.get(coef_name="upd_now_stud")						# получаем коэффициент "немедленного" обновления
		update_now = coef.coef_value
		coef.coef_value = 0																# сбрасываем коэффициент "немедленного" обновления
		coef.save()
	except:
		# если коэффициентов в базе нет, проводим обновление
		update_now = 1										
		print "Error while checking last students update time"

# запускаем процедуру обновления, если включен механизм автоматического обновления (интервал обновлений > 0) и пройден интервал обновлений, или выставлен коэффициент немедленного обновления
	if ((ic != 0) and (time_interval > datetime.timedelta(days=ic))) or (update_now > 0): 
		cursor = connections['lms'].cursor()
		# достаем из базы LMS информацию по пользователям
		cursor.execute("select mdl_user.id, mdl_user.firstname, mdl_user.lastname, mdl_user.email from mdl_user")
		raw = cursor.fetchall()
		for lms_student in raw:
			try:													# обновляем студента, если он есть в базе
				local_student = Student.objects.get(unique_number = lms_student[0])
				local_student.firstname = lms_student[1]
				local_student.lastname = lms_student[2]
				local_student.mail = lms_student[3]
				local_student.save()
			except:													# добавляем студента, если его нет в базе
				local_student = Student()
				local_student.firstname = lms_student[1]
				local_student.lastname = lms_student[2]
				local_student.mail = lms_student[3]
				local_student.unique_number = lms_student[0]
				local_student.save()

# добавляем запись в таблицу Update
		update = Update()
		update.upd_type = 0
		update.upd_date = now
		update.save()

# функция обновления таблицы курсов (обновления ведутся только вручную, системы интервалов обновления для курсов нет)
def update_courses(now):
	update_now = 0
	try:
		coef = Coefficient.objects.get(coef_name="upd_now_crs")			# получаем коэффицент "немедленного" обновления
		update_now = coef.coef_value
		coef.coef_value = 0
		coef.save()
	except:
		print "Error while checking last students update time"

	if (update_now > 0):
		cursor = connections['lms'].cursor()
		# достаем из базы LMS информацию по курсам		
		cursor.execute("select mdl_course.id, mdl_course.fullname, mdl_course.shortname from mdl_course")
		raw = cursor.fetchall()
		for lms_course in raw:
			try:
				local_course = Course.objects.get(crs_name_lms_db = lms_course[0]) 		# если курс уже есть, не трогаем его
			except:																		# если курса нет, добавляем его с дефолтными пар-ми
				local_course = Course()
				local_course.crs_name = lms_course[1]
				local_course.crs_shortname = lms_course[2]
				local_course.hours_lect = 1
				local_course.hours_pract = 1
				local_course.hours_lab = 1
				local_course.hours_self = 1
				local_course.crs_project = 0
				local_course.control_type = 0
				local_course.crs_name_lms_db = lms_course[0]
				local_course.save()

# добавляем запись в таблицу апдейтов
		update = Update()
		update.upd_type = 2
		update.upd_date = now
		update.save()

# функция обновления таблицы средних оценок
def update_total_marks(now):
	update_now = 0
	ic = 0
	time_interval = datetime.timedelta(0)
	try:
		updates_stud = Update.objects.filter(upd_type__exact=1).aggregate(last=Max('upd_date'))
		last_stud_update = updates_stud.get('last')									# получаем дату последнего апдейта средних оценок
		time_interval = now - last_stud_update										# считаем разницу относительно текущей даты
		ic = int(Coefficient.objects.get(coef_name="upd_int_mark").coef_value)		# получаем интервал обновлений
		coef = Coefficient.objects.get(coef_name="upd_now_mark")					# получаем коэффициент "немедленного" обновления
		update_now = coef.coef_value
		coef.coef_value = 0															# сбрасываем коэффициент "немедленного" обновления
		coef.save()
	except:
		# если в базе нет нужных коэффициентов, проводим обновление
		print "Error while checking last marks update time"
		update_now = 1																

# запускаем процедуру обновления, если включен механизм автоматического обновления (интервал обновлений > 0) и пройден интервал обновлений, или выставлен коэффициент немедленного обновления
	if ((ic != 0) and (time_interval > datetime.timedelta(days=ic))) or (update_now > 0):
		student_list = Student.objects.all()
		course_list = Course.objects.all()
		cursor = connections['lms'].cursor()
		
		for student in student_list:
			for course in course_list:
				mark_avg = 0.0
				try:
					# для каждого студента по каждому курсу тщем его оценки
					cursor.execute("select mdl_grade_grades.rawgrade, mdl_grade_grades.rawgrademax, mdl_grade_grades.rawgrademin from mdl_grade_grades JOIN mdl_grade_items ON mdl_grade_grades.itemid=mdl_grade_items.id WHERE mdl_grade_grades.userid=%s AND mdl_grade_grades.rawgrade IS NOT NULL AND mdl_grade_items.courseid=%s",[student.unique_number,course.crs_name_lms_db])
					raw = cursor.fetchall()
					# если было найдено 1 или несколько оценок, сохраняем среднее значение в базу или обновляем его
					if len(raw) > 0:
						points = 0
						mark_count = 0
						for element in raw:
							# переводим оценку в 100-бальную систему: 100*(Mreal-Mmin)/(Mmax-Mmin)
							points += ((element[0] - element[2])*100)/(element[1] - element[2]) 
							mark_count += 1
						if (mark_count != 0):
							mark_avg = points / mark_count
							if (mark_avg != 0):
								try:													# вариант с обновлением средней оценки
									mark = course.mark_set.get(stud=student.stud_id)
									mark.mark_avg = int(mark_avg)
									mark.save()

								except(Mark.DoesNotExist):								# вариант с созданием новой оценки
									mark = Mark()
									mark.stud = student
									mark.crs = course
									mark.mark_avg = int(mark_avg)
									mark.mark_final = 0
									mark.save()	
					
				except:
					print "Error while accessing LMS"

#добавляем запись в таблицу апдейтов
		update = Update()
		update.upd_type = 1
		update.upd_date = now
		update.save()					

# функция обновления оценок по компетенциям
def update_competence_marks(now):
	update_now = 0
	ic = 0
	time_interval = datetime.timedelta(0)
	try:
		updates_stud = Update.objects.filter(upd_type__exact=3).aggregate(last=Max('upd_date'))
		last_stud_update = updates_stud.get('last')										# получаем дату последнего апдейта оценок по комп-ям
		time_interval = now - last_stud_update											# считаем разницу относительно текущей даты
		ic = int(Coefficient.objects.get(coef_name="upd_int_comp").coef_value)			# получаем интервал обновлений
		coef = Coefficient.objects.get(coef_name="upd_now_comp")						# получаем коэффициент "немедленного" обновления
		update_now = coef.coef_value
		coef.coef_value = 0																# сбрасываем коэффициент "немедленного" обновления
		coef.save()
	except:
		# при ошибке считывания коэффициентов, проводим синхронизацию
		print "Error while checking last competence marks update time"
		update_now = 1

# запускаем процедуру обновления, если включен механизм автоматического обновления (интервал обновлений > 0) и пройден интервал обновлений, или выставлен коэффициент немедленного обновления
	if ((ic != 0) and (time_interval > datetime.timedelta(days=ic))) or (update_now > 0):
		student_list = Student.objects.all()
		course_list = Course.objects.all()
		cc_list = CompinCrs.objects.all()
		cursor = connections['lms'].cursor()
		
		for student in student_list:
			for cc in cc_list:
				mark_comp = 0.0
				# при наличии для компетенции идентификатора теста, по которому можно извлечь соответствующую оценку, запускаем процедуру обновления для каждого из студентов
				if (cc.cmpt_test_id != 0):
					try:
						cursor.execute("select mdl_grade_grades.rawgrade, mdl_grade_grades.rawgrademax, mdl_grade_grades.rawgrademin from mdl_grade_grades JOIN mdl_grade_items ON mdl_grade_grades.itemid=mdl_grade_items.id WHERE mdl_grade_grades.userid=%s AND mdl_grade_grades.rawgrade IS NOT NULL AND mdl_grade_grades.itemid=%s",[student.unique_number,cc.cmpt_test_id])
						raw = cursor.fetchall()
						# при наличии оценки за соответствующий тест запускаем процедуру обновления
						if len(raw) > 0:
							for element in raw:
								mark_comp = ((element[0] - element[2])*100)/(element[1] - element[2])
							try:														# вариант с обновлением оценки при ее наличии
								markc = cc.markforcomp_set.get(stud=student.stud_id)		
								markc.mark_comp = int(mark_comp)
								markc.save()

							except(MarkforComp.DoesNotExist):							# вариант с добавлением новой оценки
								markc = MarkforComp()
								markc.stud = student
								markc.cc = cc
								markc.mark_comp = int(mark_comp)
								markc.save()	
					
					except:
						print "Error while accessing LMS"

#добавляем запись в таблицу апдейтов
		update = Update()
		update.upd_type = 3
		update.upd_date = now
		update.save()
